/*!
 * Code block dialog plugin for Editor.md
 *
 * @file        code-block-dialog.js
 * @author      pandao
 * @version     1.2.0
 * @updateTime  2015-03-07
 * {@link       https://github.com/pandao/editor.md}
 * @license     MIT
 */

(function () {

	var factory = function (exports) {
		var cmEditor;
		var pluginName = "code-block-dialog";

		// for CodeBlock dialog select
		var codeLanguages = exports.codeLanguages = {
			asp: ["ASP", "vbscript"],
			actionscript: ["ActionScript(3.0)/Flash/Flex", "clike"],
			bash: ["Bash/Bat", "shell"],
			css: ["CSS", "css"],
			c: ["C", "clike"],
			cpp: ["C++", "clike"],
			csharp: ["C#", "clike"],
			coffeescript: ["CoffeeScript", "coffeescript"],
			d: ["D", "d"],
			dart: ["Dart", "dart"],
			delphi: ["Delphi/Pascal", "pascal"],
			erlang: ["Erlang", "erlang"],
			go: ["Golang", "go"],
			groovy: ["Groovy", "groovy"],
			html: ["HTML", "text/html"],
			java: ["Java", "clike"],
			json: ["JSON", "text/json"],
			javascript: ["Javascript", "javascript"],
			lua: ["Lua", "lua"],
			less: ["LESS", "css"],
			markdown: ["Markdown", "gfm"],
			"objective-c": ["Objective-C", "clike"],
			php: ["PHP", "php"],
			perl: ["Perl", "perl"],
			python: ["Python", "python"],
			r: ["R", "r"],
			rst: ["reStructedText", "rst"],
			ruby: ["Ruby", "ruby"],
			sql: ["SQL", "sql"],
			sass: ["SASS/SCSS", "sass"],
			shell: ["Shell", "shell"],
			scala: ["Scala", "clike"],
			swift: ["Swift", "clike"],
			vb: ["VB/VBScript", "vb"],
			xml: ["XML", "text/xml"],
			yaml: ["YAML", "yaml"]
		};

		exports.fn.codeBlockDialog = function () {

			var _this = this;
			var cm = this.cm;
			var lang = this.lang;
			var editor = this.editor;
			var settings = this.settings;
			var cursor = cm.getCursor();
			var selection = cm.getSelection();
			var classPrefix = this.classPrefix;
			var dialogName = classPrefix + pluginName, dialog;
			var dialogLang = lang.dialog.codeBlock;

			cm.focus();

			if (editor.find("." + dialogName).length > 0) {
				dialog = editor.find("." + dialogName);
				dialog.find("option:first").attr("selected", "selected");
				dialog.find("textarea").val(selection);

				this.dialogShowMask(dialog);
				this.dialogLockScreen();
				dialog.show();
			}
			else {
				var dialogHTML = "<div class=\"" + classPrefix + "code-toolbar\">" +
					dialogLang.selectLabel + "<select><option selected=\"selected\" value=\"\">" + dialogLang.selectDefaultText + "</option></select>" +
					"</div>" +
					"<textarea placeholder=\"请输入代码...\" style=\"display:none;\">" + selection + "</textarea>";

				dialog = this.createDialog({
					name: dialogName,
					title: dialogLang.title,
					width: 780,
					height: 565,
					mask: settings.dialogShowMask,
					drag: settings.dialogDraggable,
					content: dialogHTML,
					lockScreen: settings.dialogLockScreen,
					maskStyle: {
						opacity: settings.dialogMaskOpacity,
						backgroundColor: settings.dialogMaskBgColor
					},
					buttons: {
						enter: [lang.buttons.enter, function () {
							var codeTexts = this.find("textarea").val();
							var langName = this.find("select").val();

							if (langName === "") {
								alert(lang.dialog.codeBlock.unselectedLanguageAlert);
								return false;
							}

							if (codeTexts === "") {
								alert(lang.dialog.codeBlock.codeEmptyAlert);
								return false;
							}

							langName = (langName === "other") ? "" : langName;

							cm.replaceSelection(["```" + langName, codeTexts, "```"].join("\n"));

							if (langName === "") {
								cm.setCursor(cursor.line, cursor.ch + 3);
							}

							this.hide().lockScreen(false).hideMask();

							return false;
						}],
						cancel: [lang.buttons.cancel, function () {
							this.hide().lockScreen(false).hideMask();

							return false;
						}]
					}
				});
			}

			var langSelect = dialog.find("select");

			if (langSelect.find("option").length === 1) {
				for (var key in codeLanguages) {
					var codeLang = codeLanguages[key];
					langSelect.append("<option value=\"" + key + "\" mode=\"" + codeLang[1] + "\">" + codeLang[0] + "</option>");
				}

				langSelect.append("<option value=\"other\">" + dialogLang.otherLanguage + "</option>");
			}

			var mode = langSelect.find("option:selected").attr("mode");

			var cmConfig = {
				mode: (mode) ? mode : "text/html",
				theme: settings.theme,
				tabSize: 4,
				autofocus: true,
				autoCloseTags: true,
				indentUnit: 4,
				lineNumbers: true,
				lineWrapping: true,
				extraKeys: { "Ctrl-Q": function (cm) { cm.foldCode(cm.getCursor()); } },
				foldGutter: true,
				gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
				matchBrackets: true,
				indentWithTabs: true,
				styleActiveLine: true,
				styleSelectedText: true,
				autoCloseBrackets: true,
				showTrailingSpace: true,
				highlightSelectionMatches: true
			};

			var textarea = dialog.find("textarea");
			var cmObj = dialog.find(".CodeMirror");

			if (dialog.find(".CodeMirror").length < 1) {
				cmEditor = exports.$CodeMirror.fromTextArea(textarea[0], cmConfig);
				cmObj = dialog.find(".CodeMirror");

				cmObj.css({
					"float": "none",
					margin: "8px 0",
					border: "1px solid #ddd",
					fontSize: settings.fontSize,
					width: "100%",
					height: "390px"
				});

				cmEditor.on("change", function (cm) {
					textarea.val(cm.getValue());
				});
			}
			else {

				cmEditor.setValue(cm.getSelection());
			}

			langSelect.change(function () {
				var _mode = $(this).find("option:selected").attr("mode");
				cmEditor.setOption("mode", _mode);
			});
		};

	};

	// CommonJS/Node.js
	if (typeof require === "function" && typeof exports === "object" && typeof module === "object") {
		module.exports = factory;
	}
	else if (typeof define === "function")  // AMD/CMD/Sea.js
	{
		if (define.amd) { // for Require.js

			define(["editormd"], function (editormd) {
				factory(editormd);
			});

		} else { // for Sea.js
			define(function (require) {
				var editormd = require("./../../editormd");
				factory(editormd);
			});
		}
	}
	else {
		factory(window.editormd);
	}

})();
